package cn.wostore.wxhelper.Xposed;

import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Process;
import cn.wostore.wxhelper.bean.ForwardRule;
import cn.wostore.wxhelper.utils.FileUtil;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * 模拟微信消息发送的具体实现
 *
 * @author wuch
 * @date 2019/1/4 0004
 */
public class SendMessageUtil {
    private ClassLoader classLoader;
    private Activity activity;
    private ContentValues contentValues;
    private List<ForwardRule> ruleList = new ArrayList<>();
    private Object msgRetransmitUI;

    public SendMessageUtil(ClassLoader classLoader, Activity activity, ContentValues contentValues) {
        this.classLoader = classLoader;
        this.activity = activity;
        this.contentValues = contentValues;
        Class<?> clazzA = XposedHelpers.findClassIfExists("com.tencent.mm.ui.transmit.MsgRetransmitUI", classLoader);
        this.msgRetransmitUI = XposedHelpers.newInstance(clazzA);
    }


    public void reply() {
        /*消息类型：1为文字消息（包含基础表情符），34为语音消息*/
        final int type = contentValues.getAsInteger("type");
        final String talker = contentValues.getAsString("talker");
        XposedBridge.log("消息来源: " + talker+", 消息类型: "+type);
        /*启动新线程连接数据库，防止微信进程被阻塞*/
        new Thread(new Runnable() {
            @Override
            public void run() {
                getForwardRule();
                if (ruleList.size() == 0) {
                    XposedBridge.log("规则数量" + String.valueOf(ruleList.size()));
                    return;
                }
                for (ForwardRule forwardRule : ruleList) {
                    if (forwardRule.isForwardRuleState()) {
                        if (forwardRule.getForwardMainGroupId().equals(talker)) {
                            //判断规则开关是否打开以及消息来源群是否匹配
                            if (type == 1) {//判断消息类型是否为文本
                                XposedBridge.log("直播主群 " + forwardRule.getForwardMainGroupId());
                                for (String id : getGroupIds(forwardRule)) {
                                    if (contentValues.getAsInteger("isSend") == 0) {
                                        String[] contents = contentValues.getAsString("content").split(":\n", 2);
                                        if (contents[0].equals(forwardRule.getForwardMasterId())) {
                                            replyTextMessage(contents[1], id);
                                            XposedBridge.log("回复" + id);
                                            try {
                                                Thread.sleep(1000);
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                    }

                                }
                            } else if (type == 34) {//判断消息类型是否为语音
                                XposedBridge.log("直播主群" + forwardRule.getForwardMainGroupId());
                                for (String id : getGroupIds(forwardRule)) {
                                    if (contentValues.getAsInteger("isSend") == 0) {
                                        String[] contents = contentValues.getAsString("content").split(":");
                                        if (contents[0].equals(forwardRule.getForwardMasterId())) {
                                            String fileName = contentValues.getAsString("imgPath");
                                            try {
                                                Thread.sleep(1000);
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                            XposedBridge.log(contents[1]);
                                            forwardVoiceMsg(fileName, id, Integer.parseInt(contents[1]));
                                            XposedBridge.log("回复" + id);
                                        }
                                    }

                                }
                            } else if (type == 3){
                                XposedBridge.log("直播主群" + forwardRule.getForwardMainGroupId());
                                for (String id : getGroupIds(forwardRule)) {
                                    if (contentValues.getAsInteger("isSend") == 0) {
                                        int msgId = contentValues.getAsInteger("msgId");
                                        long msgSvrId = contentValues.getAsLong("msgSvrId");
                                        String[] contents = contentValues.getAsString("content").split(":");
                                        XposedBridge.log(contentValues.toString());
                                        if (contents[0].equals(forwardRule.getForwardMasterId())) {
                                            try {
                                                Thread.sleep(1000);
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                            XposedBridge.log(contents[1]);
                                            forwardImgMessage(contents[1], id, msgId, msgSvrId);
                                            XposedBridge.log("回复" + id);
                                        }
                                    }
                                }
                            } else if (type ==43){
                                XposedBridge.log("直播主群" + forwardRule.getForwardMainGroupId());
                                for (final String id : getGroupIds(forwardRule)) {
                                    if (contentValues.getAsInteger("isSend") == 0) {
                                        final String imgPath = contentValues.getAsString("imgPath");
                                        int msgId = contentValues.getAsInteger("msgId");
                                        String[] contents = contentValues.getAsString("content").split(":");
                                        XposedBridge.log(contentValues.toString());
                                        if (contents[0].equals(forwardRule.getForwardMasterId())) {
                                            try {
                                                Thread.sleep(1000);
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                            forwardVideoMessage(msgId, imgPath, id, talker);
                                            XposedBridge.log("回复" + id);
                                        }
                                    }
                                }
                            } else if (type == 49){
                                XposedBridge.log("直播主群" + forwardRule.getForwardMainGroupId());
                                for (String id : getGroupIds(forwardRule)) {
                                    if (contentValues.getAsInteger("isSend") == 0) {
                                        int msgId = contentValues.getAsInteger("msgId");
                                        long msgSvrId = contentValues.getAsLong("msgSvrId");
                                        String[] contents = contentValues.getAsString("content").split(":");
                                        String msg = contents[1].trim();
                                        XposedBridge.log("msgId: "+msgId);
                                        XposedBridge.log("msgSvrId: "+msgSvrId);
                                        XposedBridge.log("msg: "+msg);
                                        if (contents[0].equals(forwardRule.getForwardMasterId())) {
                                            try {
                                                Thread.sleep(1000);
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                            forwardFile(id, msgId, msgSvrId, msg);
                                            XposedBridge.log("回复" + id);
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }
        }).start();

    }

    /**
     * 转发的子群的id列表构建
     *
     * @param forwardRule 转发规则实例对象
     * @return 要转发的群组id列表
     */
    private List<String> getGroupIds(ForwardRule forwardRule) {
        return Arrays.asList(forwardRule.getForwardChildGroupIds().split(";"));
    }

    /**
     * 获取所有的规则列表
     */
    private void getForwardRule() {
        XposedBridge.log("getForwardRule()");
        Uri uri = Uri.parse("content://cn.wostore.wxhelper.provider/ForwardRule");
        Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
        XposedBridge.log("wxhelper xposed pid "+Process.myPid());
//        Cursor cursor = DaoHandler.getInstance().query("ForwardRule", null, null, null, null);
        if (cursor != null) {
            XposedBridge.log("getForwardRule: cursor count :"+cursor.getCount());
            while (cursor.moveToNext()) {
                ForwardRule forwardRule = new ForwardRule();
                forwardRule.setValues(cursor);
                ruleList.add(forwardRule);
            }
            cursor.close();
        } else {
            XposedBridge.log("getForwardRule: cursor null");
        }
    }

    //回复文本消息
    private void replyTextMessage(String strContent, final String strChatroomId) {
        XposedBridge.log("准备回复消息内容：content:" + strContent + ",chatroomId:" + strChatroomId);
        if (strContent == null || strChatroomId == null
                || strContent.length() == 0 || strChatroomId.length() == 0) {
            return;
        }

        //构造new里面的参数：l iVar = new i(aao, str, hQ, i2, mVar.cvb().fD(talkerUserName, str));
        Class<?> classiVar = XposedHelpers.findClassIfExists("com.tencent.mm.modelmulti.h", classLoader);
        Object objectiVar = XposedHelpers.newInstance(classiVar,
                new Class[]{String.class, String.class, int.class, int.class, Object.class},
                strChatroomId, strContent, 1, 1, new HashMap<String, String>() {{
                    put(strChatroomId, strChatroomId);
                }});
        Object[] objectParamiVar = new Object[]{objectiVar, 0};

        //创建静态实例对象au.Dk()，转换为com.tencent.mm.ah.p对象
        Class<?> classG = XposedHelpers.findClassIfExists("com.tencent.mm.kernel.g", classLoader);
        Object objectG = XposedHelpers.callStaticMethod(classG, "DO");
        Object objectdpP = XposedHelpers.getObjectField(objectG, "dJT");


        //查找au.Dk().a()方法
        Class<?> classDF = XposedHelpers.findClassIfExists("com.tencent.mm.ah.p", classLoader);
        Class<?> classI = XposedHelpers.findClassIfExists("com.tencent.mm.ah.m", classLoader);
        Method methodA = XposedHelpers.findMethodExactIfExists(classDF, "a", classI, int.class);

        //调用发消息方法
        try {
            XposedBridge.invokeOriginalMethod(methodA, objectdpP, objectParamiVar);
            XposedBridge.log("invokeOriginalMethod()执行成功");
        } catch (Exception e) {
            XposedBridge.log("调用微信消息回复方法异常");
            XposedBridge.log(e);
        }
    }

    private void forwardVoiceMsg(String fileName, String chatroomId, int length) {
        Class<?> classiVar1 = XposedHelpers.findClassIfExists("com.tencent.mm.modelvoice.q", classLoader);
        String sourcePath = (String) XposedHelpers.callStaticMethod(classiVar1, "getFullPath", fileName);
        String newFileName = (String) XposedHelpers.callStaticMethod(classiVar1, "oz", chatroomId);
        String desPath = (String) XposedHelpers.callStaticMethod(classiVar1, "getFullPath", newFileName);
        File sourceFile = new File(sourcePath);
        File desFile = new File(desPath);
        try {
            FileUtil.copyFile(sourceFile, desFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        XposedBridge.log("源文件位置为：" + sourcePath);
        XposedBridge.log("目标文件位置为：" + desPath);
        boolean b = (boolean) XposedHelpers.callStaticMethod(classiVar1, "m", newFileName, length, 0);
        XposedBridge.log("q.m方法执行结果为：" + b);
        Class class2 = XposedHelpers.findClassIfExists("com.tencent.mm.modelvoice.m", classLoader);
        Object object = XposedHelpers.callStaticMethod(class2, "Ti");
        XposedHelpers.callMethod(object, "run");
    }

    //转发图片消息
    private void forwardImgMessage(String strContent, String strChatroomId, int msgId, long msgSvrId) {
        XposedBridge.log("准备回复消息内容：content:" + strContent + ",chatroomId:" + strChatroomId);

        if (strContent == null || strChatroomId == null
                || strContent.length() == 0 || strChatroomId.length() == 0) {
            return;
        }

//        Class classB = XposedHelpers.findClass("com.tencent.mm.as.o",classLoader);
//        Object object1 = XposedHelpers.callStaticMethod(classB,"OJ");
//        String fileName = (String) XposedHelpers.callMethod(object1,"F",imgPath,true);
        XposedHelpers.setLongField(this.msgRetransmitUI, "bIt", msgId);
        XposedHelpers.setIntField(this.msgRetransmitUI, "wgm", 0);
        XposedHelpers.setIntField(this.msgRetransmitUI, "wgq", 1);
        XposedHelpers.setIntField(this.msgRetransmitUI, "wgr", 1);
        XposedHelpers.setObjectField(this.msgRetransmitUI, "fileName", getImgPath(msgSvrId));
        XposedHelpers.callMethod(this.msgRetransmitUI, "a", strChatroomId, 4, null);
    }

    private String getImgPath(long msgSvrId){
        Class classO = XposedHelpers.findClass("com.tencent.mm.as.o", classLoader);
        Object objectOJ = XposedHelpers.callStaticMethod(classO, "OJ");
        Object bX = XposedHelpers.callMethod(objectOJ, "bX", msgSvrId);

        Class classF = XposedHelpers.findClass("com.tencent.mm.as.f", classLoader);
        String o = XposedHelpers.callStaticMethod(classF, "c", bX).toString();
        String path = XposedHelpers.callMethod(objectOJ, "o", o, null, null).toString();

        XposedBridge.log("[o] "+o+", [path] "+path);
        return path;
    }



    //转发视频消息
    private void forwardVideoMessage(int msgId, String imgPath, final String strChatroomId, String talker) {
        XposedBridge.log("准备回复消息内容：imgPath:" + imgPath + ",chatroomId:" + strChatroomId);
        XposedBridge.log("当前执行线程: "+ Thread.currentThread().getName());
        if (imgPath == null || strChatroomId == null
                || imgPath.length() == 0 || strChatroomId.length() == 0) {
            return;
        }
//        //方法1：尝试Hook com.tencent.mm.modelvideo.u.a 转发不成功，但是执行无任何报错，只好放弃。
//        Class<?> clazzA = XposedHelpers.findClassIfExists("com.tencent.mm.modelvideo.u", classLoader);
//        Object objectS =  XposedHelpers.callStaticMethod(clazzA, "oe", imgPath);
//        Object objectbwa = XposedHelpers.getObjectField(objectS, "eHQ");
//        int videoLength = XposedHelpers.getIntField(objectS, "eHH");
//        XposedHelpers.callStaticMethod(clazzA, "a",
//                imgPath, videoLength, strChatroomId, null, 0, "", 43, objectbwa, null);

//        //方法2：尝试Hook  com.tencent.mm.ui.transmit.MsgRetransmitUI$a，注意AsyncTask要在main线程中执行。
//        //activity.runOnUiThread(new Runnable{ run(){//在这里调用forwardVideoMessage()方法}})
//        //转发不成功，但是执行无任何报错，说明错过了重要步骤，只好放弃，往上一级。
//        Class class1 = XposedHelpers.findClass("com.tencent.mm.ui.transmit.MsgRetransmitUI$a", classLoader);
//        XposedBridge.log("forwardVideoMessage: class1 success");
//        Object object1 = XposedHelpers.newInstance(class1);
//        XposedBridge.log("forwardVideoMessage: object1 success");
//        Class class2 = XposedHelpers.findClass("com.tencent.mm.ui.transmit.MsgRetransmitUI$b", classLoader);
//        XposedBridge.log("forwardVideoMessage: class2 success");
//        Object object2 = XposedHelpers.newInstance(class2);
//        XposedBridge.log("forwardVideoMessage: object2 success");
//        XposedHelpers.setObjectField(object1, "fileName", imgPath);
//        XposedHelpers.setIntField(object1, "wgl", 0);
//        XposedHelpers.setIntField(object1, "eFO", 1);
//        XposedHelpers.setBooleanField(object1, "wgR", false);
//        XposedHelpers.setObjectField(object1, "userName", strChatroomId);
//        XposedHelpers.setBooleanField(object1, "wgS", true);
//        XposedHelpers.setBooleanField(object1, "wgj", false);
//        XposedHelpers.setObjectField(object1, "wgV", object2);
//        XposedHelpers.setObjectField(object1, "context", activity);
//        Class class3 = XposedHelpers.findClass("com.tencent.mm.modelvideo.u", classLoader);
//        XposedBridge.log("forwardVideoMessage: class3 success");
//        Object object3 = XposedHelpers.callStaticMethod(class3, "oe", imgPath);
//        XposedBridge.log("forwardVideoMessage: object3 success");
//        XposedHelpers.setObjectField(object1, "wgU", XposedHelpers.getObjectField(object3, "eHQ"));
//        XposedHelpers.setIntField(object1, "eHH", XposedHelpers.getIntField(object3, "eHH"));
//        XposedBridge.log("forwardVideoMessage: wgU ： "+XposedHelpers.getObjectField(object3, "eHQ")
//                +" eHH: "+XposedHelpers.getIntField(object3, "eHH"));
//        Object object4 = XposedHelpers.callMethod(object3, "SA");
//        XposedHelpers.setObjectField(object1, "czr", object4);
//        XposedHelpers.callMethod(object1, "execute", new Object[]{new Object[0]});

//        //方法3  com.tencent.mm.ui.transmit.MsgRetransmitUI.a, 构造Dialog失败。
//        //Attempt to invoke virtual method 'android.view.WindowManagerImpl android.view.WindowManagerImpl.createLocalWindowManager(android.view.Window)' on a null object reference
//        XposedHelpers.setLongField(msgRetransmitUI, "bIt", msgId);
//        XposedHelpers.setIntField(msgRetransmitUI, "wgl", 1);
//        XposedHelpers.setIntField(msgRetransmitUI, "length", 4);
//        XposedHelpers.setObjectField(msgRetransmitUI, "mBase", activity.getBaseContext());
//        XposedHelpers.setIntField(msgRetransmitUI, "msgType", 1);
//        XposedHelpers.setBooleanField(msgRetransmitUI, "wgj", true);
//        XposedHelpers.setObjectField(msgRetransmitUI, "fileName", imgPath);
//        Class classb = XposedHelpers.findClassIfExists("com.tencent.mm.ui.transmit.MsgRetransmitUI$b", classLoader);
//        Object objectb = XposedHelpers.newInstance(classb);
//        XposedHelpers.setObjectField(objectb, "wgX", Arrays.asList(strChatroomId));
//        XposedHelpers.setBooleanField(objectb, "bIe", true);
//        XposedHelpers.callMethod(msgRetransmitUI, "a", objectb, strChatroomId);



        //方法4 Hook cJs方法, 注意需要设置mBase字段，否则getString(),getResources(),getPackageName()等方法会调用失败。
        XposedHelpers.setObjectField(msgRetransmitUI, "mBase", activity.getBaseContext());
        Class class1 = XposedHelpers.findClass("com.tencent.mm.modelvideo.u", classLoader);
        Object object1 = XposedHelpers.callStaticMethod(class1, "oe", imgPath);
        XposedHelpers.setIntField(msgRetransmitUI, "length", XposedHelpers.getIntField(object1, "eHH"));
        XposedHelpers.setLongField(msgRetransmitUI, "bIt", msgId);
        XposedHelpers.setObjectField(msgRetransmitUI, "fileName", imgPath);
        XposedHelpers.setIntField(msgRetransmitUI, "wgm", 0);
        XposedHelpers.setIntField(msgRetransmitUI, "msgType", 1);
        //XposedHelpers.setObjectField(msgRetransmitUI, "bVV", null);
        XposedHelpers.setBooleanField(msgRetransmitUI, "wgt", false);
        XposedHelpers.setIntField(msgRetransmitUI, "wgy", 0);

        XposedHelpers.setObjectField(msgRetransmitUI, "wgg",  Arrays.asList(strChatroomId));
        XposedHelpers.setLongField(msgRetransmitUI, "startTime", System.currentTimeMillis() / 1000);
        XposedHelpers.setIntField(msgRetransmitUI, "wgC", 1);
        XposedHelpers.setIntField(msgRetransmitUI, "wgD", 0);
        XposedHelpers.setObjectField(msgRetransmitUI, "wgA", strChatroomId);
        XposedHelpers.setObjectField(msgRetransmitUI, "wgB", talker);
        XposedHelpers.callMethod(msgRetransmitUI, "cJs");

    }

    private void forwardFile(String strChatroomId, int msgId, long msgSvrId, String msg){
        XposedHelpers.setLongField(msgRetransmitUI, "bIt", msgId);
        XposedHelpers.setIntField(msgRetransmitUI, "vDF", -1);
        XposedHelpers.setBooleanField(msgRetransmitUI, "vfS", false);
        XposedHelpers.setObjectField(msgRetransmitUI, "wgh", null);
        XposedHelpers.setObjectField(msgRetransmitUI, "bVV", msg);
        String fkV = "SessionId@" + Long.valueOf(msgSvrId)+"#"+System.nanoTime();
        XposedBridge.log("fkV: "+fkV);
        XposedHelpers.setObjectField(msgRetransmitUI, "fKV", fkV);
        XposedHelpers.callMethod(msgRetransmitUI, "aeo", strChatroomId);
    }

}
